package com.caiden_micheal.permission.service.impl;

import com.caiden_micheal.base.constant.LoggerHead;
import com.caiden_micheal.base.domain.AjxResult;
import com.caiden_micheal.base.dto.PageDTO;
import com.caiden_micheal.base.utils.RedisUtil;
import com.caiden_micheal.base.vo.PageVo;
import com.caiden_micheal.permission.domain.Permission;
import com.caiden_micheal.permission.dto.FindPermissionSelectData;
import com.caiden_micheal.permission.mapper.PermissionMapper;
import com.caiden_micheal.permission.service.PermissionService;
import com.caiden_micheal.permission.vo.PermissionQueryVO;
import com.caiden_micheal.user.domain.User;
import com.caiden_micheal.user.mapper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class PermissionServiceImpl implements PermissionService {
    private static final Logger logger = LoggerFactory.getLogger(PermissionServiceImpl.class);

    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private PositionAuthorityMapper positionAuthorityMapper;
    @Autowired
    private OrgAuthorityMapper orgAuthorityMapper;
    @Autowired
    private UserAuthorityMapper userAuthorityMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PositionOrgUserMapper positionOrgUserMapper;

    @Override
    public PageDTO findPermissionsByCondition(PermissionQueryVO permissionQueryVO) {
        if (permissionQueryVO == null) {
            logger.warn(LoggerHead.warnHead() + "permissionQueryVO is Null!");
            return null;
        }
        return extractFindPermissionByCondition(permissionQueryVO);
    }


    @Override
    public PageDTO findPermissionsByConditionMenu(PermissionQueryVO permissionQueryVO) {
        if (permissionQueryVO == null || permissionQueryVO.getMenuId() == null) {
            logger.warn(LoggerHead.warnHead() + "permissionQueryVO is Null OR permissionQueryVO.menuId is Null!");
            return null;
        }
        return extractFindPermissionByCondition(permissionQueryVO);
    }

    @Override
    public PageDTO findPermissionsByConditionExcludePositionId(PermissionQueryVO permissionQueryVO) {
        PageVo page = permissionQueryVO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "permissionQueryVO.page is Null!");
            return null;
        }
        List<Long> authorityIdList;
        if (permissionQueryVO.getPositionId() != null) {
            authorityIdList = positionAuthorityMapper.findAuthorityIdsByPositionId(permissionQueryVO.getPositionId());
            if (authorityIdList.size() == 0) {
                authorityIdList = null;
            }
        } else {
            return null;
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<Permission> orgList = permissionMapper.findPermissionListPaginationQueryExcludeUserId(permissionQueryVO, authorityIdList);
        page.setCount(permissionMapper.findPermissionListQueryCountExcludeUserId(permissionQueryVO, authorityIdList));
        return new PageDTO(orgList, page);
    }

    @Override
    public PageDTO findPermissionsByConditionExcludeOrgId(PermissionQueryVO permissionQueryVO) {
        PageVo page = permissionQueryVO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "permissionQueryVO.page is Null!");
            return null;
        }
        List<Long> authorityIdList;
        if (permissionQueryVO.getOrgId() != null) {
            authorityIdList = orgAuthorityMapper.findAuthorityIdsByOrgId(permissionQueryVO.getOrgId());
            if (authorityIdList.size() == 0) {
                authorityIdList = null;
            }
        } else {
            return null;
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<Permission> orgList = permissionMapper.findPermissionListPaginationQueryExcludeUserId(permissionQueryVO, authorityIdList);
        page.setCount(permissionMapper.findPermissionListQueryCountExcludeUserId(permissionQueryVO, authorityIdList));
        return new PageDTO(orgList, page);
    }

    @Override
    public PageDTO permissionQueryExcludeUserId(PermissionQueryVO permissionQueryVO) {
        PageVo page = permissionQueryVO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "permissionQueryVO.page is Null!");
            return null;
        }
        List<Long> authorityIdList;
        if (permissionQueryVO.getUserId() != null) {
            authorityIdList = userAuthorityMapper.findAuthorityIdsByUserId(permissionQueryVO.getUserId());
            if (authorityIdList.size() == 0) {
                authorityIdList = null;
            }
        } else {
            return null;
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<Permission> orgList = permissionMapper.findPermissionListPaginationQueryExcludeUserId(permissionQueryVO, authorityIdList);
        page.setCount(permissionMapper.findPermissionListQueryCountExcludeUserId(permissionQueryVO, authorityIdList));
        return new PageDTO(orgList, page);
    }

    @Transactional
    @Override
    public AjxResult addPermission(Permission permission) {
        if (permission == null || permission.getAuthorityAlias() == null || permission.getAuthorityName() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        return extractAddPermission(permission);
    }

    @Override
    public AjxResult addPermissionWithMenuId(Permission permission) {
        if (permission == null || permission.getAuthorityAlias() == null || permission.getAuthorityName() == null || permission.getMenuId() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        return extractAddPermission(permission);
    }

    private AjxResult extractAddPermission(Permission permission) {
        if (permission.getAuthorityAlias().length() >= 9 && ":menuView".equals(permission.getAuthorityAlias().substring(permission.getAuthorityAlias().length() - 9))) {
            return AjxResult.paramError("不允许用户将权限别名修改为以[:menuView]结尾");
        }
        try {
            Permission data = permissionMapper.findByName(permission.getAuthorityName());
            if (data == null) {
                permissionMapper.addPermission(permission);
                return AjxResult.success("创建成功");
            } else {
                return AjxResult.repetitiveError("权限名称已存在");
            }
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult editPermission(Permission permission) {
        if (permission == null || permission.getId() == null || permission.getAuthorityAlias() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        if (permission.getAuthorityAlias().length() >= 9 && ":menuView".equals(permission.getAuthorityAlias().substring(permission.getAuthorityAlias().length() - 9))) {
            return AjxResult.paramError("不允许用户将权限别名修改为以[:menuView]结尾");
        }
        try {
            Permission tempPermission = permissionMapper.findById(permission.getId());
            if (tempPermission == null) {
                return AjxResult.paramError("权限不存在");
            } else if (tempPermission.getAuthorityAlias().length() >= 9 && ":menuView".equals(tempPermission.getAuthorityAlias().substring(tempPermission.getAuthorityAlias().length() - 9))) {
                return AjxResult.paramError("菜单权限不允许修改");
            }
            Permission resData = new Permission();
            resData.setId(permission.getId());
            resData.setAuthorityAlias(permission.getAuthorityAlias());
            permissionMapper.update(resData);
            return AjxResult.success("修改成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Override
    public Permission findById(Long permissionId) {
        return permissionMapper.findById(permissionId);
    }

    @Transactional
    @Override
    public AjxResult removePermission(Long permissionId) {
        if (permissionId == null) {
            return AjxResult.paramError("参数传入有误");
        }
        Permission permission = permissionMapper.findById(permissionId);
        if (permission == null) {
            return AjxResult.paramError("权限不存在");
        }
        try {
            List<Long> userIdList = new ArrayList<>();
            if (permission.getUserCount() != 0) {
                userIdList.addAll(userAuthorityMapper.findUserIdsByAuthorityId(permissionId));
            }
            if (permission.getOrgCount() != 0) {
                List<Long> orgIdList = orgAuthorityMapper.findOrgIdsByAuthorityId(permissionId);
                for (Long orgId : orgIdList) {
                    userIdList.addAll(userMapper.findUserIdsByOrgId(orgId));
                }
            }
            if (permission.getPositionCount() != 0) {
                List<Long> positionIdList = positionAuthorityMapper.findPositionIdsByAuthorityId(permissionId);
                for (Long positionId : positionIdList) {
                    userIdList.addAll(positionOrgUserMapper.findUserIdsByPositionId(positionId));
                }
            }
            userAuthorityMapper.removeByPermissionId(permissionId);
            orgAuthorityMapper.removeByPermissionId(permissionId);
            positionAuthorityMapper.removeByPermissionId(permissionId);
            permissionMapper.removeById(permissionId);
            for (Long userId : userIdList) {
                String key = "caiden_micheal:user:" + userId + ":*";
                RedisUtil.deleteFold(key);
            }
            return AjxResult.success("删除成功，注意：正在强制所有相关用户重新登录赋权");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("操作数据库异常");
        }
    }

    @Override
    public AjxResult findPermissionSelectData(FindPermissionSelectData findPermissionSelectData) {
        if (findPermissionSelectData == null || findPermissionSelectData.getDisplayName() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        try {
            return AjxResult.success(permissionMapper.findPermissionSelectData(findPermissionSelectData.getDisplayName()));
        } catch (Exception e) {
            logger.error(e.toString());
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    private PageDTO extractFindPermissionByCondition(PermissionQueryVO permissionQueryVO) {
        PageVo page = permissionQueryVO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "permissionQueryVO.page is Null!");
            return null;
        }
        List<Long> authorityIdList = null;
        if (permissionQueryVO.getPositionId() != null) {
            authorityIdList = positionAuthorityMapper.findAuthorityIdsByPositionId(permissionQueryVO.getPositionId());
            if (authorityIdList.size() == 0) {
                return null;
            }
        } else if (permissionQueryVO.getOrgId() != null) {
            authorityIdList = orgAuthorityMapper.findAuthorityIdsByOrgId(permissionQueryVO.getOrgId());
            if (authorityIdList.size() == 0) {
                return null;
            }
        } else if (permissionQueryVO.getUserId() != null) {
            // user_authority 查询用户权限
            List<Long> userAuthorityIdList = userAuthorityMapper.findAuthorityIdsByUserId(permissionQueryVO.getUserId());
            // 查询用户的部门和职位 查询权限
            User user = new User();
            user.setId(permissionQueryVO.getUserId());
            user = userMapper.findOne(user);
            if (user == null) {
                logger.warn(LoggerHead.warnHead() + permissionQueryVO.getUserId() + " UserId, User non-exist!");
                return null;
            }
            // 查询其职位
            List<Long> positionIdList = positionOrgUserMapper.findPositionIdsByUserId(permissionQueryVO.getUserId());
            List<Long> positionAuthorityIdList;
            if (positionIdList == null || positionIdList.size() == 0) {
                positionAuthorityIdList = new ArrayList<>();
            } else {
                positionAuthorityIdList = positionAuthorityMapper.findAuthorityIdsByOrgIds(positionIdList);
            }
            List<Long> orgIdList = positionOrgUserMapper.findOrgIdsByUserId(permissionQueryVO.getUserId());
            if (orgIdList == null || positionIdList.size() == 0) {
                orgIdList = new ArrayList<>();
                orgIdList.add(user.getOrgId());
            } else {
                if (!orgIdList.contains(user.getOrgId())) {
                    orgIdList.add(user.getOrgId());
                }
            }
            List<Long> orgAuthorityIdList = orgAuthorityMapper.findAuthorityIdsByOrgIds(orgIdList);
            Set<Long> set = new HashSet<>(userAuthorityIdList);
            set.addAll(orgAuthorityIdList);
            set.addAll(positionAuthorityIdList);
            authorityIdList = new ArrayList<>(set);
            if (authorityIdList.size() == 0) {
                return null;
            }
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<Permission> orgList = permissionMapper.findByIdListPaginationQuery(permissionQueryVO, authorityIdList);
        page.setCount(permissionMapper.findPermissionListQueryCount(permissionQueryVO, authorityIdList));
        return new PageDTO(orgList, page);
    }
}